﻿#include "return_multi_type.h"
// C/C++ 学习网站：https://legacy.cplusplus.com 注意旧版本（搜索）和新版本

/*
返回堆区指针在 C 中通过动态内存分配实现。这里只是增加了一些 C++ 实现
	1.返回 C++ 的结构体（类）指针
	2.返回 vector 数组
	3.返回 tuple 元组、pair 元组
*/

static Person add_person(const Person& p1, const Person& p2) {//返回一个堆区结构体指针变量
	return Person(p1.name + " and " + p2.name, p1.age + p2.age, p1.money + p2.money);
	// 返回结构体变量，推荐使用
}

static vector<double>* add_array(const vector<double>& v1)
{//返回一个堆区 vector 数组，本质上同上面的结构体指针
	vector<double>* v = new vector<double>;
	v->reserve(1);
	double sum = 0;
	for (auto s : v1)
		sum += s;
	v->emplace_back(sum);
	return v; // 返回 vector 数组的指针
}

static vector<double>* add_array(const vector<double>& v1,
	const vector<double>& v2) { // 同上面的结构体指针，只是增加了一个参数
	if (v1.size() != v2.size()) {
		std::cout << "Error: the two arrays have different sizes." << std::endl;
		return nullptr;
	}
	vector<double>* v = new vector<double>;
	v->reserve(v1.size());
	for (size_t i = 0; i < v1.size(); i++)
		v->emplace_back(v1[i] + v2[i]);
	return v; // 返回 vector 数组
}

static std::tuple<int, double, string> add_tuple(
	const std::tuple<int, double, string>& t1,
	const std::tuple<int, double, string>& t2) {
	return std::make_tuple(std::get<0>(t1) + std::get<0>(t2),  // 返回 tuple 元组
		std::get<1>(t1) + std::get<1>(t2), std::get<2>(t1) + ' ' + std::get<2>(t2));
}

static void print_this_tuple(const std::tuple<int, double, string>& t) {
	cout << "The tuple is: "
		<< std::get<0>(t) << "    "
		<< std::get<1>(t) << "    "
		<< std::get<2>(t) << endl;
}

static std::pair<string, double> add_pair(
	const std::pair<string, double>& p1,
	const std::pair<string, double>& p2) {
	return std::make_pair(p1.first + " and " + p2.first, p1.second + p2.second);
}

void test_return() {
	// 测试返回多个类型值 - 返回结构体
	Person p1("Tom", 20, 1000.5);
	Person p2("Jerry", 30, 2000.8);
	Person p = add_person(p1, p2);
	std::cout << p << std::endl;
	//delete p; // 释放堆区指针指向内存

	// 测试返回多个类型值 - 返回 vector 数组：只能返回一种类型，这里返回 string 数组指针
	vector<double> v1 = { 1.1, 2.2, 3.3, 4.4, 5.5 };
	vector<double>* vp1 = add_array(v1);
	cout << "The sum of the array is: " << vp1->at(0) << endl;
	delete vp1; // 释放堆区内存
	vector<double>* vp2 = new vector<double>;
	vp2 = add_array(v1, v1);
	for (auto s : *vp2)
		cout << s << "    ";
	cout << endl;
	delete vp2; // 释放内存

	// 测试返回多个类型值 - 返回 tuple 元组
	std::tuple<int, double, string> t1(10, 3.14, "Hello");
	std::tuple<int, double, string> t2(20, 2.71, "World");
	std::tuple<int, double, string> t4; // 也可以直接赋值给另一个变量
	{
		auto t3 = add_tuple(t1, t2); // 返回一个 tuple 元组，注意内存是在栈区分配的
		std::get<0>(t3) = 300; // 修改元组元素
		int* p = &std::get<0>(t3); // 也可以通过指针修改元组元素
		print_this_tuple(t3);
		t4 = t3; // 也可以赋值给另一个变量
	}
	print_this_tuple(t4); // 输出 t4 的值，
	// 不需要销毁，因为在栈区分配的，暂时保存值，退出作用域后，当有函数等创建时，值会变
//t4.swap(t1); // 也可以交换两个元组的值

// std::pair 的用法（类似于 python 的字典）:
	std::pair<string, double> p3("Jane", 314159.26);
	std::pair<string, double> p4("Tom", 271828.18);
	auto p5 = add_pair(p3, p4); // 返回一个 pair 元组，注意是在堆区分配的
	cout << "The pair of p5 is: " << p5.first << "    " << p5.second << endl;
}
